package tools

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

// HTTPTool provides HTTP request capabilities
type HTTPTool struct {
	client *http.Client
}

// NewHTTPTool creates a new HTTP tool
func NewHTTPTool() *HTTPTool {
	return &HTTPTool{
		client: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}

// Name implements Tool
func (t *HTTPTool) Name() string {
	return "http"
}

// Description implements Tool
func (t *HTTPTool) Description() string {
	return "Makes HTTP requests to external services"
}

// Parameters implements Tool
func (t *HTTPTool) Parameters() []Parameter {
	return []Parameter{
		{
			Name:        "method",
			Type:        "string",
			Description: "HTTP method (GET, POST, PUT, DELETE)",
			Required:    true,
		},
		{
			Name:        "url",
			Type:        "string",
			Description: "URL to request",
			Required:    true,
		},
		{
			Name:        "headers",
			Type:        "object",
			Description: "HTTP headers",
			Required:    false,
			Default:     map[string]string{},
		},
		{
			Name:        "body",
			Type:        "string",
			Description: "Request body",
			Required:    false,
		},
	}
}

// Execute implements Tool
func (t *HTTPTool) Execute(ctx context.Context, params map[string]interface{}) (interface{}, error) {
	method, ok := params["method"].(string)
	if !ok {
		return nil, fmt.Errorf("method parameter is required")
	}

	url, ok := params["url"].(string)
	if !ok {
		return nil, fmt.Errorf("url parameter is required")
	}

	// Create request
	var body string
	if b, ok := params["body"].(string); ok {
		body = b
	}

	req, err := http.NewRequestWithContext(ctx, method, url, strings.NewReader(body))
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %v", err)
	}

	// Add headers
	if headers, ok := params["headers"].(map[string]interface{}); ok {
		for k, v := range headers {
			if str, ok := v.(string); ok {
				req.Header.Set(k, str)
			}
		}
	}

	// Make request
	resp, err := t.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request failed: %v", err)
	}
	defer resp.Body.Close()

	// Read response
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response: %v", err)
	}

	// Try to parse JSON response
	var jsonResp interface{}
	if err := json.Unmarshal(respBody, &jsonResp); err == nil {
		return map[string]interface{}{
			"status":  resp.StatusCode,
			"headers": resp.Header,
			"body":    jsonResp,
		}, nil
	}

	// Return raw response if not JSON
	return map[string]interface{}{
		"status":  resp.StatusCode,
		"headers": resp.Header,
		"body":    string(respBody),
	}, nil
}
